﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Simulator
{
	public partial class Logger : UserControl
	{
		// TODO: remove this and use loggerArea1.SelectedBridge
		Bridge _selectedBridge;

		public Logger ()
		{
			InitializeComponent ();

			string path = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "STP Logs");
			textBoxSaveLocation.Text = path;
		}

		public void AppendText (Bridge bridge, int portIndex, int treeIndex, string str)
		{
			loggerArea1.AppendText (bridge, portIndex, treeIndex, str);
		}

		void UpdateTextBoxTree (out int selectedTreeIndex)
		{
			if (comboBoxVLAN1.SelectedVlanNumber == -1)
			{
				selectedTreeIndex = -1;
				textBoxTree.Text = "(all trees)";
			}
			else
			{
				selectedTreeIndex = _selectedBridge.Wrapper.GetTreeIndexFromVlanNumber ((ushort) comboBoxVLAN1.SelectedVlanNumber);
				if (selectedTreeIndex == 0)
					textBoxTree.Text = "CIST";
				else
					textBoxTree.Text = String.Format ("MSTI {0}", selectedTreeIndex);
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="bridge"></param>
		/// <param name="portIndex">-1 to display the log relevant to all ports, or zero-based port number to display only information relevant to that port.</param>
		/// <param name="vlanNumber">-1 to display the log relevant to all vlans, or 1..4094 to display only information relavant to a specific vlan.</param>
		public void Select (Bridge bridge, int portIndex, int vlanNumber)
		{
			if (bridge == null)
			{
				// Deselecting the selected bridge, if any.

				if (_selectedBridge != null)
				{
					// A bridge was selected before.
					_selectedBridge = null;

					textBoxSelectedBridgeName.Text = "(none)";

					comboBoxPort.Items.Clear ();
					comboBoxVLAN1.SelectVlan (-1);

					loggerArea1.Select (null, -1, -1);

					this.Enabled = false;
				}
			}
			else
			{
				// Selecting a bridge (a new one or the same).

				if ((portIndex < -1) || (portIndex >= bridge.PortCount))
					throw new ArgumentOutOfRangeException ("portIndex must be >= -1 and < bridge.PortCount", "portIndex");

				if ((vlanNumber != -1) && ((vlanNumber < 1) || (vlanNumber > 4094)))
					throw new ArgumentOutOfRangeException ("vlanNumber must be -1, or 1..4094", "vlanNumber");

				if (_selectedBridge != bridge)
				{
					// The caller is selecting a different bridge. Repopulate the tree combobox and port combobox.

					_selectedBridge = bridge;

					textBoxSelectedBridgeName.Text = bridge.Name;

					// port combo box
					comboBoxPort.Items.Clear ();
					comboBoxPort.Items.Add ("(all ports)");
					for (int pi = 0; pi < bridge.PortCount; pi++)
						comboBoxPort.Items.Add (String.Format ("PORT {0}", pi + 1));
				}

				comboBoxPort.SelectedIndex = portIndex + 1;

				comboBoxVLAN1.SelectVlan (vlanNumber);

				int selectedTreeIndex;
				UpdateTextBoxTree (out selectedTreeIndex);

				loggerArea1.Select (_selectedBridge, portIndex, selectedTreeIndex);

				this.Enabled = true;
			}
		}

		void comboBoxPort_SelectionChangeCommitted (object sender, EventArgs e)
		{
			if (_selectedBridge != null)
			{
				int portIndex = comboBoxPort.SelectedIndex - 1;

				loggerArea1.Select (_selectedBridge, portIndex, loggerArea1.SelectedTreeIndex);
			}
		}

		void buttonCopy_Click (object sender, EventArgs e)
		{
			loggerArea1.CopyAll ();
		}

		void buttonClear_Click (object sender, EventArgs e)
		{
			loggerArea1.Clear ();
		}

		protected override void OnClientSizeChanged (EventArgs e)
		{
			base.OnClientSizeChanged (e);

			// workaround for anchoring / docking not working together with DPI scaling
			// http://connect.microsoft.com/VisualStudio/feedback/details/259155

			int padding = 0;
			loggerArea1.Left = padding;
			loggerArea1.Width = ClientSize.Width - padding - padding;
			loggerArea1.Height = ClientSize.Height - loggerArea1.Top - padding;
		}

		private void comboBoxVLAN1_VlanChanged (object sender, EventArgs e)
		{
			if (_selectedBridge != null)
			{
				int selectedTreeIndex;
				UpdateTextBoxTree (out selectedTreeIndex);

				loggerArea1.Select (_selectedBridge, loggerArea1.SelectedPortIndex, selectedTreeIndex);
			}
		}

		private void buttonSave_Click (object sender, EventArgs e)
		{
			StringBuilder sb = new StringBuilder ();

			if (Directory.Exists (textBoxSaveLocation.Text))
			{
				foreach (var f in Directory.GetFiles (textBoxSaveLocation.Text, "*.log"))
					File.Delete (f);
			}
			else
				Directory.CreateDirectory (textBoxSaveLocation.Text);

			foreach (var kvp in loggerArea1.EntriesPerBridge)
			{
				foreach (var entry in kvp.Value)
					sb.Append (entry.Text);

				string filename = String.Format ("{0}.log", kvp.Key.Name);
				string path = Path.Combine (textBoxSaveLocation.Text, filename);
				File.WriteAllText (path, sb.ToString (), Encoding.UTF8);

				sb.Clear ();
			}

			Process.Start ("explorer.exe", textBoxSaveLocation.Text);
		}
	}
}
